

package cn.shengchao.dubbo.api.distribute;

import cn.hutool.core.collection.CollUtil;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeNodeInfo;
import cn.shengchao.examstar.rpc.base.PageResult;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeContentInfo;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeNodeRoleChain;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeContentInfoService;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeNodeInfoService;
import cn.shengchao.examstar.distribute.model.DistributeNodeRoleChainExistModel;
import cn.shengchao.examstar.distribute.ohs.local.appservice.DistributeNodeRoleChainExistLoader;
import cn.shengchao.examstar.rpc.base.TransResult;
import cn.shengchao.examstar.rpc.distribute.bi.DistributeContentBI;
import cn.shengchao.examstar.rpc.distribute.dto.CourseNodesDistributeTree;
import cn.shengchao.examstar.rpc.distribute.dto.CourseNodesDistributeTreeNodesVo;
import cn.shengchao.examstar.rpc.distribute.dto.DistributeContentBatchDto;
import cn.shengchao.examstar.rpc.distribute.req.CourseDistributeQueryPage;
import cn.shengchao.examstar.rpc.distribute.req.CourseDistributeUserQueryPage;
import cn.shengchao.examstar.rpc.distribute.resp.CourseDistributeForUserRespEntity;
import cn.shengchao.examstar.rpc.distribute.resp.CourseDistributeRespEntity;
import cn.shengchao.examstar.rpc.distribute.enums.DistributeContentRoleEnum;
import cn.shengchao.examstar.rpc.distribute.enums.DistributeContentUserRelationEnum;
import cn.shengchao.examstar.rpc.distribute.enums.DistributeDataStatusEnum;
import cn.shengchao.examstar.rpc.distribute.enums.DistributeTypeEnum;
import cn.shengchao.examstar.product.ohs.local.appservice.CourseService;
import cn.shengchao.examstar.product.ohs.local.message.KnowledgeNodeDto;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: examstarapi
 * @description: 内容分销综合业务
 * @author: Xiong weiqiang
 * @create: 2025-03-29 14:40
 */
@DubboService
public class DistributeContentBIService implements DistributeContentBI {
    @Autowired
    private DistributeNodeInfoService distributeNodeInfoService;
    @Autowired
    private DistributeContentInfoService distributeContentInfoService;

    @Autowired
    private CourseService courseService;
    @Autowired
    private DistributeNodeRoleChainExistLoader distributeNodeRoleChainExistLoader;

    @Override
    public List<CourseNodesDistributeTreeNodesVo> getCourseNodesTreeVo(Long courseId) {
        List<KnowledgeNodeDto> knowledgeList = courseService.getKnowledgeList(courseId, "", false);
        List<DistributeContentInfo> distributeContentInfoList = new ArrayList<>();
        List<DistributeNodeInfo> authorNodeList = new ArrayList<>();
        List<DistributeNodeInfo> contentOwnerNodeList = new ArrayList<>();
        if (CollUtil.isNotEmpty(knowledgeList)) {
            List<Long> ids = knowledgeList.stream()
                    .filter(a -> a.getIsLesson() != null && a.getIsLesson() == 1L)
                    .map(KnowledgeNodeDto::getId)
                    .toList();
            if (CollUtil.isNotEmpty(ids)) {
                distributeContentInfoList = distributeContentInfoService.list(Wrappers.lambdaQuery(DistributeContentInfo.class)
                        .in(DistributeContentInfo::getContentId, ids)
                        .eq(DistributeContentInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
            }
        }
        if (CollUtil.isNotEmpty(distributeContentInfoList)) {
            authorNodeList = distributeNodeInfoService.list(Wrappers.lambdaQuery(DistributeNodeInfo.class)
                    .in(DistributeNodeInfo::getUserId, distributeContentInfoList.stream().map(DistributeContentInfo::getAuthorUserId).toList())
                    .eq(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus())
                    .eq(DistributeNodeInfo::getDistributeType, DistributeTypeEnum.TYPE_CTPD.getType())
            );
            contentOwnerNodeList = distributeNodeInfoService.list(Wrappers.lambdaQuery(DistributeNodeInfo.class)
                    .in(DistributeNodeInfo::getUserId, distributeContentInfoList.stream().map(DistributeContentInfo::getContentDistributeUserId).toList())
                    .eq(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus())
                    .eq(DistributeNodeInfo::getDistributeType, DistributeTypeEnum.TYPE_CTPD.getType())
            );
        }
        return convertKnowledgeNodesToCourseNodesVos(knowledgeList, distributeContentInfoList, authorNodeList, contentOwnerNodeList);
    }


    @Override
    public List<CourseNodesDistributeTree> getCourseNodesTree(Long courseId, Long userId) {
        List<KnowledgeNodeDto> knowledgeList = courseService.getKnowledgeList(courseId, "", false);
        List<DistributeContentInfo> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(knowledgeList)) {
            List<Long> ids = knowledgeList.stream()
                    .filter(a -> a.getIsLesson() != null && a.getIsLesson() == 1L)
                    .map(KnowledgeNodeDto::getId)
                    .toList();
            if (CollUtil.isNotEmpty(ids)) {
                list = distributeContentInfoService.list(Wrappers.lambdaQuery(DistributeContentInfo.class)
                        .in(DistributeContentInfo::getContentId, ids)
                        .eq(DistributeContentInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
            }
        }

        return convertKnowledgeNodesToCourseNodes(knowledgeList, list, userId);
    }

    @Override
    public PageResult<CourseDistributeRespEntity> getCourseDistributeList(CourseDistributeQueryPage courseDistributeQueryPage) {
        return distributeContentInfoService.getCourseDistributePageList(courseDistributeQueryPage);
    }


    @Override
    public PageResult<CourseDistributeForUserRespEntity> getCourseDistributeListForUser(CourseDistributeUserQueryPage courseDistributeQueryPage) {
        return distributeContentInfoService.getCourseDistributeForUserPageList(courseDistributeQueryPage);
    }

    /**
     * method : distributeContentRegister
     * description : 内容登记分销比例
     *
     * @param distributeContentBatchDto \{@link DistributeContentBatchDto \}
     * @author : Xiong weiqiang
     * @CreateDate : 2025-03-29 14:41:34
     *
     * @Reviewed :
     * @UpdateLog : Name Date Reason/Contents
     *            ---------------------------------------
     *            **** **** ****
     *
     */
    @Override
    public TransResult<String> distributeContentRegister(DistributeContentBatchDto distributeContentBatchDto) {
        Long authorUserId = distributeContentBatchDto.getAuthorUserId();
        //加载用户的分销关系，分销链表
        DistributeNodeRoleChainExistModel existModel = distributeNodeRoleChainExistLoader
                .loadModelByUserId(authorUserId, DistributeTypeEnum.TYPE_CTPD.getType());
        Long distributeUserId = null;
        if (existModel != null) {
            DistributeNodeRoleChain distributeNodeRoleChain = existModel.getDistributeNodeRoleChain();
            //如果是员工，则取上级的分销用户id
            if (distributeNodeRoleChain.getRefRoleCode()
                    .equals(DistributeContentRoleEnum.ROLE_CTPD_EMP.getCode()) && existModel.getUpLevelNodeInfo() != null) {
                distributeUserId = existModel.getUpLevelNodeInfo().getUserId();
            } else {
                distributeUserId = distributeNodeRoleChain.getRefUserId();
            }
        }
        distributeContentBatchDto.setDistributeUserId(distributeUserId);
        //检查超50%
        Map<Long,String> productMap  = distributeContentInfoService.checkContentPercent(distributeContentBatchDto);
        if (!productMap.isEmpty()) {
            return TransResult.fail(productMap.values().toArray()[0]+"内容登记分销比例超过50%");
        }
        distributeContentInfoService.registerNewProducts(distributeContentBatchDto);
        return TransResult.success();
    }

    @Override
    public void distributeContentClear(DistributeContentBatchDto distributeContentBatchDto) {
        distributeContentInfoService.clearProducts(distributeContentBatchDto);
    }

    public List<CourseNodesDistributeTree> convertKnowledgeNodesToCourseNodes(List<KnowledgeNodeDto> knowledgeList,
                                                                              List<DistributeContentInfo> list, Long userId) {
        Map<Long, BigDecimal> percentMap = new HashMap<>();
        Map<Long, BigDecimal> availPercentMap = new HashMap<>();
        Map<Long,List<DistributeContentInfo>> groupMap = list.stream().collect(Collectors.groupingBy(DistributeContentInfo::getContentId));
        if (CollUtil.isNotEmpty(knowledgeList)){
            for (KnowledgeNodeDto dto:knowledgeList){
                List<DistributeContentInfo> existNodeList=groupMap.getOrDefault(dto.getId(),List.of()).stream().filter(a->a.getAuthorUserId().equals(userId)).toList();
                List<DistributeContentInfo> exludeUserNodeList=groupMap.getOrDefault(dto.getId(),List.of()).stream().filter(a->!a.getAuthorUserId().equals(userId)).toList();
                BigDecimal sum=CollUtil.isNotEmpty(existNodeList)?existNodeList.stream().map(DistributeContentInfo::getStablePercent).reduce(BigDecimal.ZERO, BigDecimal::add):BigDecimal.ZERO;
                BigDecimal sum1=CollUtil.isNotEmpty(exludeUserNodeList)?exludeUserNodeList.stream().map(DistributeContentInfo::getStablePercent).reduce(BigDecimal.ZERO, BigDecimal::add):BigDecimal.ZERO;
                percentMap.put(dto.getId(),sum);
                availPercentMap.put(dto.getId(),sum1);
            }
        }
        Map<Long, List<Long>> distributeUserMap = CollUtil.isNotEmpty(list)
                ? list.stream()
                .collect(Collectors.groupingBy(DistributeContentInfo::getContentId, Collectors.mapping(DistributeContentInfo::getAuthorUserId,Collectors.toList())))
                : new HashMap<>();
        // 1. 创建ID->节点的映射
        Map<Long, CourseNodesDistributeTree> nodeMap = new HashMap<>();
        knowledgeList.forEach(dto -> {
            CourseNodesDistributeTree node = createNode(dto);
            node.setDistributePercent(percentMap.getOrDefault(node.getId(), BigDecimal.ZERO));
            if (availPercentMap.containsKey(node.getId())) {
                node.setAvailPercent(BigDecimal.valueOf(50.0d).subtract(availPercentMap.getOrDefault(node.getId(), BigDecimal.ZERO)));
            }else {
                node.setAvailPercent(BigDecimal.valueOf(50.0d));
            }
            if (distributeUserMap.containsKey(node.getId())) {
                if (CollUtil.isNotEmpty(distributeUserMap.get(node.getId()))&&distributeUserMap.get(node.getId()).contains(userId)) {
                    node.setAsUserRelation(DistributeContentUserRelationEnum.RELATION_YES.getStatus());
                } else {
                    node.setAsUserRelation(DistributeContentUserRelationEnum.RELATION_NOT_BELONG.getStatus());
                }
                node.setDistributeUserId(distributeUserMap.get(node.getId()));
            } else {
                node.setAsUserRelation(DistributeContentUserRelationEnum.RELATION_NO.getStatus());
            }
            nodeMap.put(dto.getId(), node);
        });

        // 2. 构建树形结构
        List<CourseNodesDistributeTree> rootNodes = new ArrayList<>();
        knowledgeList.forEach(dto -> {
            CourseNodesDistributeTree node = nodeMap.get(dto.getId());
            if (dto.getParentId() == null || !nodeMap.containsKey(dto.getParentId())) {
                rootNodes.add(node); // 根节点
            } else {
                CourseNodesDistributeTree parent = nodeMap.get(dto.getParentId());
                parent.getChildren().add(node); // 添加子节点
            }
        });

        // 3. 计算根节点价格（子节点价格之和）
        rootNodes.forEach(root -> {
            if (!root.getChildren().isEmpty()) {
                BigDecimal sum = root.getChildren()
                        .stream()
                        .map(CourseNodesDistributeTree::getPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                root.setPrice(sum);
            }
        });

        // 4. 排序（根据sort字段）
        sortTree(rootNodes);
        return rootNodes;
    }

    private CourseNodesDistributeTree createNode(KnowledgeNodeDto dto) {
        CourseNodesDistributeTree node = new CourseNodesDistributeTree();
        node.setId(dto.getId());
        node.setCourseId(dto.getCourseId());
        node.setIsLesson(dto.getIsLesson());
        node.setParentId(dto.getParentId());
        node.setName(dto.getName());
        node.setPrice(BigDecimal.valueOf(dto.getPrice()));
        node.setDiscountPrice(BigDecimal.ZERO); // 默认无折扣
        node.setSort(dto.getSort()); // 默认排序值
        node.setChildren(new ArrayList<>());
        return node;
    }

    private void sortTree(List<CourseNodesDistributeTree> nodes) {
        nodes.forEach(node -> {
            // 递归排序子节点
            if (!node.getChildren().isEmpty()) {
                node.getChildren().sort(Comparator.comparingInt(CourseNodesDistributeTree::getSort));
                sortTree(node.getChildren());
            }
        });
    }

    private List<CourseNodesDistributeTreeNodesVo> convertKnowledgeNodesToCourseNodesVos(List<KnowledgeNodeDto> knowledgeList, List<DistributeContentInfo> distributeContentInfoList, List<DistributeNodeInfo> authorNodeList, List<DistributeNodeInfo> contentOwnerNodeList) {

        Map<Long, BigDecimal> percentMap = CollUtil.isNotEmpty(distributeContentInfoList)
                ? distributeContentInfoList.stream()
                .collect(Collectors.toMap(DistributeContentInfo::getContentId, DistributeContentInfo::getStablePercent))
                : new HashMap<>();

        Map<Long, DistributeContentInfo> distributeContentInfoMap = CollUtil.isNotEmpty(distributeContentInfoList)
                ? distributeContentInfoList.stream()
                .collect(Collectors.toMap(DistributeContentInfo::getContentId, a -> a))
                : new HashMap<>();
        Map<Long, DistributeNodeInfo> authorNodeMap = CollUtil.isNotEmpty(authorNodeList)
                ? authorNodeList.stream()
                .collect(Collectors.toMap(DistributeNodeInfo::getUserId, a -> a, (v1, v2) -> v2))
                : new HashMap<>();
        Map<Long, DistributeNodeInfo> contentOwnerMap = CollUtil.isNotEmpty(contentOwnerNodeList)
                ? contentOwnerNodeList.stream()
                .collect(Collectors.toMap(DistributeNodeInfo::getUserId, a -> a, (v1, v2) -> v2))
                : new HashMap<>();
        // 1. 创建ID->节点的映射
        Map<Long, CourseNodesDistributeTreeNodesVo> nodeMap = new HashMap<>();
        knowledgeList.forEach(dto -> {
            CourseNodesDistributeTreeNodesVo node = createNodesVo(dto);
            if (percentMap.containsKey(node.getId())) {
                node.setDistributePercent(percentMap.get(node.getId()));
            }
            if (distributeContentInfoMap.containsKey(node.getId())) {
                Long authorNodeUserId = distributeContentInfoMap.get(node.getId()).getAuthorUserId();
                Long contentNodeUserId = distributeContentInfoMap.get(node.getId()).getContentDistributeUserId();
                if (authorNodeMap.containsKey(authorNodeUserId)) {
                    node.setAuthorUserId(authorNodeMap.get(authorNodeUserId).getUserId());
                    node.setAuthorNodeName(authorNodeMap.get(authorNodeUserId).getFullName());
                }
                if (contentOwnerMap.containsKey(contentNodeUserId)) {
                    node.setDistributeUserId(contentOwnerMap.get(contentNodeUserId).getUserId());
                    node.setDistributeNodeName(contentOwnerMap.get(contentNodeUserId).getFullName());
                    node.setShowNodeName(contentOwnerMap.get(contentNodeUserId).getFullName());
                }
                node.setAsUserRelation(DistributeContentUserRelationEnum.RELATION_YES.getStatus());
            } else {
                node.setAsUserRelation(DistributeContentUserRelationEnum.RELATION_NO.getStatus());
            }

            node.setDiscountPrice(percentMap.get(dto.getId()));
            nodeMap.put(dto.getId(), node);
        });

        // 2. 构建树形结构
        List<CourseNodesDistributeTreeNodesVo> rootNodes = new ArrayList<>();
        knowledgeList.forEach(dto -> {
            CourseNodesDistributeTreeNodesVo node = nodeMap.get(dto.getId());
            if (dto.getParentId() == null || !nodeMap.containsKey(dto.getParentId())) {
                rootNodes.add(node); // 根节点
            } else {
                CourseNodesDistributeTreeNodesVo parent = nodeMap.get(dto.getParentId());
                parent.getChildren().add(node); // 添加子节点
            }
        });

        // 3. 计算根节点价格（子节点价格之和）
        rootNodes.forEach(root -> {
            if (!root.getChildren().isEmpty()) {
                BigDecimal sum = root.getChildren()
                        .stream()
                        .map(CourseNodesDistributeTreeNodesVo::getPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                root.setPrice(sum);
            }
        });

        // 4. 排序（根据sort字段）
        sortNodesTree(rootNodes);
        return rootNodes;
    }

    private CourseNodesDistributeTreeNodesVo createNodesVo(KnowledgeNodeDto dto) {
        CourseNodesDistributeTreeNodesVo node = new CourseNodesDistributeTreeNodesVo();
        node.setId(dto.getId());
        node.setCourseId(dto.getCourseId());
        node.setIsLesson(dto.getIsLesson());
        node.setParentId(dto.getParentId());
        node.setName(dto.getName());
        node.setPrice(BigDecimal.valueOf(dto.getPrice()));
        node.setDiscountPrice(BigDecimal.ZERO); // 默认无折扣
        node.setSort(dto.getSort()); // 默认排序值
        node.setChildren(new ArrayList<>());
        return node;
    }

    private void sortNodesTree(List<CourseNodesDistributeTreeNodesVo> nodes) {
        nodes.forEach(node -> {
            // 递归排序子节点
            if (!node.getChildren().isEmpty()) {
                node.getChildren().sort(Comparator.comparingInt(CourseNodesDistributeTreeNodesVo::getSort));
                sortNodesTree(node.getChildren());
            }
        });
    }
}